package com.founder.tool.xml;

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;

/**
 *
 * <entity type="com.founder.entity.Order">
 *   <entityItem name="date">2012-02-01 00:00:00</entityItem>
 *   <entityItem name="name">Joe</entityItem>
 *   <entityItem name="status">
 *     <entity type="com.founder.entity.OrderStatus">
 *       <entityItem name="status">true</entityItem>
 *     </entity>
 *   </entityItem>
 *   <entityItem name="orderItems">
 *     <entityList>
 *       <entity type="com.founder.entity.OrderItem">
 *         <entityItem name="product">111</entityItem>
 *         <entityItem name="quantity">2</entityItem>
 *         <entityItem name="price">8.9</entityItem>
 *       </entity>
 *       <entity type="com.founder.entity.OrderItem">
 *         <entityItem name="product">112</entityItem>
 *         <entityItem name="quantity">22</entityItem>
 *         <entityItem name="price">8.92</entityItem>
 *       </entity>
 *     </entityList>
 *   </entityItem>
 *   <entityItem name="orderId">0</entityItem>
 * </entity>
 * 
 * <entityList>
 *   <entity type="com.founder.entity.OrderItem">
 *     <entityItem name="product">111</entityItem>
 *     <entityItem name="quantity">2</entityItem>
 *     <entityItem name="price">8.9</entityItem>
 *   </entity>
 *   <entity type="com.founder.entity.OrderItem">
 *     <entityItem name="product">112</entityItem>
 *     <entityItem name="quantity">22</entityItem>
 *     <entityItem name="price">8.92</entityItem>
 *   </entity>
 * </entityList>
 * 
 * 
 * @author chen_weihua
 *
 */
public class Entity2Xml {
	
	private StringBuffer xml = new StringBuffer();
	
	public Entity2Xml(Object obj) {
		if (obj.getClass().isArray()) {
			setCollectionTagBegin();
            int length = Array.getLength(obj);
            for (int i = 0; i < length; i++) {
            	xml.append(Entity2Xml.wrap(Array.get(obj, i)).toString());
            }
            setCollectionTagEnd();
        } else {
    		setEntityTagBegin(obj);
    		setItemsXml(obj);
    		setEntityTagEnd();
        }
	}
	
	@SuppressWarnings("unchecked")
	public Entity2Xml(Collection collection) {
		if (collection != null) {
			setCollectionTagBegin();
			Iterator iter = collection.iterator();
			while (iter.hasNext()) {
			    Object obj = iter.next();
			    xml.append(Entity2Xml.wrap(obj).toString());
			}
			setCollectionTagEnd();
		}
	}
	
	public String toString() {
		return xml.toString();
	}
	
	private void setItemsXml(Object bean) {
		Class<?> klass = bean.getClass();
        Field[] fields = klass.getDeclaredFields();
        String name = null;
        Object value = null;
        for (Field field : fields) {
        	name = field.getName();
        	value = getValue(field, bean);
        	if (value != null) {
        		setEntityItem(name, value.toString());
        	}
        }
	}
	
	private Object getValue(Field f, Object bean) {
		Class<?> cls = bean.getClass();
		Object value = null;
		try {
            Method fieldGetMet = cls.getMethod(StringUtil.parGetName(f.getName()), new Class[] {});  
            Object fieldVal = fieldGetMet.invoke(bean, new Object[] {});
			value = wrap(fieldVal);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return value;
	}
	
	private void setEntityItem(String name, String value) {
		xml.append("<" + EntityTag.ENTITY_ITEM);
		xml.append(" " + EntityTag.ENTITY_ATTR_NAME + "=" + "\"" + name + "\"");
		xml.append(">" + value + "</" + EntityTag.ENTITY_ITEM + ">");
	}
	
	private void setEntityTagBegin(Object obj) {
		String name = obj.getClass().getSimpleName();
		xml.append("<" + EntityTag.ENTITY);
		xml.append(" " + EntityTag.ENTITY_ATTR_TYPE + "=" + "\"" + name + "\"");
		xml.append(">");
	}
	
	private void setEntityTagEnd() {
		xml.append("</" + EntityTag.ENTITY + ">");
	}
	
	private void setCollectionTagBegin() {
		xml.append("<" + EntityTag.ENTITY_LIST + ">");
	}
	
	private void setCollectionTagEnd() {
		xml.append("</" + EntityTag.ENTITY_LIST + ">");
	}
	
    @SuppressWarnings("unchecked")
	static Object wrap(Object object) {
        try {
            if (object == null) {
                return null;
            }
            
            if (object instanceof Byte   || object instanceof Character ||
                    object instanceof Short  || object instanceof Integer   ||
                    object instanceof Long   || object instanceof Boolean   || 
                    object instanceof Float  || object instanceof Double    ||
                    object instanceof String) {
                return object;
            }
            
            if (object instanceof Date) {
                return StringUtil.fmtDate((Date)object);
            }
            
            if (object instanceof Collection) {
                return new Entity2Xml((Collection)object);
            }
            if (object.getClass().isArray()) {
                return new Entity2Xml(object);
            }
            if (object instanceof Map) {
            	return "";//暂不支持
                //return new Entity2Xml((Map)object);
            }
            Package objectPackage = object.getClass().getPackage();
            String objectPackageName = ( objectPackage != null ? objectPackage.getName() : "" );
            if (objectPackageName.startsWith("java.") ||
           		 objectPackageName.startsWith("javax.") ||
           		 object.getClass().getClassLoader() == null) {
                return object.toString();
            }
            return new Entity2Xml(object);
        } catch(Exception exception) {
            return null;
        }
    }

}
